/*
 * Copyright 2009 Cedric Priscal
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */

package com.zhiwei.cppapp.serialport;

import android.util.Log;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 串口设备寻找类，用于查询设备的串口
 */
public class SerialPortFinder {
    //TAG 标签，用于日志标识
    private static final String TAG = "SerialPort";
    //设备列表,原来代码使用的是Vector，现在改成List
    private List<Driver> mDrivers = null;

    /**
     * 遍历获取串口设备列表
     *
     * @return 返回串口设备列表集合
     * @throws IOException 读写异常
     */
    private List<Driver> getDrivers() throws IOException {
        //只有在mDrivers列表集合为空的时候，才进行遍历
        if (mDrivers == null) {
            mDrivers = new ArrayList<>();
            //linux下一切皆文件，所以/proc/tty/下面代表的串口设备文件，在这里读取drivers，获得串口设备
            LineNumberReader reader = new LineNumberReader(new FileReader("/proc/tty/drivers"));
            String line;
            //循环read，逐行读取，也逐行更新行号，所以在while条件内line = reader.readLine()
            while ((line = reader.readLine()) != null) {
                // Issue 3:设备名称包含空格的话，就没法子正确的获取设备名称
                // Since driver name may contain spaces, we do not extract driver name with split()
                String driverName = line.substring(0, 0x15).trim();//默认的设备名称，在前面的21个字符内
                //通过+符号分割字符串，得到string数组，分析新找到的设备文件
                // TODO: 2016/12/26 0026 不太理解linux驱动文件的格式，看了一下，没明白怎么split出来设备信息的。
                String[] w = line.split(" +");
                if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
                    Log.d(TAG, "Found new driver " + driverName + " on " + w[w.length - 4]);
                    mDrivers.add(new Driver(driverName, w[w.length - 4]));
                }
            }
            //关闭文件流
            reader.close();
        }
        return mDrivers;
    }

    /**
     * 获取所有的设备信息
     *
     * @return 返回string数组，包含设备信息
     */
    public String[] getAllDevices() {
        //此处原来的代码用的vector，改用list
        List<String> devices = new ArrayList<>();
        // Parse each driver，遍历解析各个驱动设备
        Iterator<Driver> driverIterator;
        try {
            driverIterator = getDrivers().iterator();
            while (driverIterator.hasNext()) {
                Driver driver = driverIterator.next();
                //获取单个设备的信息迭代器，此处driver.getDevices().iterator，使用while循环，用foreach代替了
                for (File file : driver.getDevices()) {
                    String device = file.getName();
                    String value = String.format("%s (%s)", device, driver.getName());
                    devices.add(value);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return devices.toArray(new String[devices.size()]);
    }

    /**
     * 获取所有设备文件的路径信息
     *
     * @return 返回设备路径信息的string数组
     */
    public String[] getAllDevicesPath() {
        //用List代替了Vector
        List<String> devices = new ArrayList<>();
        // Parse each driver，解析每个设备
        Iterator<Driver> driverIterator;
        try {
            driverIterator = getDrivers().iterator();
            while (driverIterator.hasNext()) {
                Driver driver = driverIterator.next();
                //foreach代替iterator
                for (File file : driver.getDevices()) {
                    String device = file.getAbsolutePath();
                    devices.add(device);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return devices.toArray(new String[devices.size()]);
    }

    /**
     * 内部类，linux驱动设备信息，准确的说应该是Android设备信息
     */
    private class Driver {
        private String mDriverName;//串口驱动的名称
        private String mDeviceRoot;//设备路径

        /**
         * 构造函数，驱动设备信息
         *
         * @param name 名称
         * @param root 绝对路径
         */
        Driver(String name, String root) {
            mDriverName = name;
            mDeviceRoot = root;
        }

        //原代码Vector，改用list
        List<File> mDevices = null;

        /**
         * 获取所有设备信息列表，原代码用Vector，改用list
         *
         * @return 设备信息集合
         */
        List<File> getDevices() {
            //获得设备列表信息
            if (mDevices == null) {
                mDevices = new ArrayList<>();
                File dev = new File("/dev");
                File[] files = dev.listFiles();
                int i;
                //新增设备
                for (i = 0; i < files.length; i++) {
                    if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {
                        Log.d(TAG, "Found new device: " + files[i]);
                        mDevices.add(files[i]);
                    }
                }
            }
            return mDevices;
        }

        /**
         * 获取设备名称
         *
         * @return 名称
         */
        public String getName() {
            return mDriverName;
        }
    }
}
